package com.iflytek.xfMscMain;

import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.GrammarListener;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.speech.util.FucUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class XfMain implements XfInterface {

    private static volatile XfMain sInstance;

    public static XfMain getInstance() {
        if (null == sInstance) {
            synchronized (XfMain.class) {
                sInstance = new XfMain();
            }
        }
        return sInstance;
    }


    private Toast mToast;
    // 语音识别对象
    private SpeechRecognizer mAsr;
    // 本地语法文件
    private String mLocalGrammar = null;
    // 本地语法构建路径
    private String grmPath;
    // 返回结果格式，支持：xml,json
    private String mResultType = "json";
    private final String GRAMMAR_TYPE_BNF = "bnf";
    private String mEngineType;
    private Button fileRecognizeBT;
    private String curFile = "asrfile.wav";  //音频文件名
    private Context context;


    private void myinit(Context context) {
        this.context = context;
        grmPath = context.getExternalFilesDir("msc").getAbsolutePath() + "/xfMsc";
        // 初始化识别对象
        mAsr = SpeechRecognizer.createRecognizer(context, mInitListener);
        // 初始化语法、命令词
        mLocalGrammar = FucUtil.readFile(context, "call.bnf", "utf-8");
        if (mAsr == null) {
            showTip("初始化失败  masr is null");
        } else {
            mEngineType = SpeechConstant.TYPE_LOCAL;
            mContent = new String(mLocalGrammar);
            // 设置参数
            setParam();
            ret = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, grammarListener);
            if (ret != ErrorCode.SUCCESS) {
                showTip("语法构建失败,错误码：" + ret);
            }
        }

    }


    String mContent;// 语法、词典临时变量
    int ret = 0;// 函数调用返回值

    /**
     * 初始化监听器。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {
            Log.d("buggg", "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失败,错误码：" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
            }
        }
    };

    /**
     * 构建语法监听器。
     */
    private GrammarListener grammarListener = new GrammarListener() {
        @Override
        public void onBuildFinish(String grammarId, SpeechError error) {
            if (error == null) {
                showTip("语法构建成功：" + grammarId);
            } else {
                showTip("语法构建失败,错误码：" + error.getErrorCode());
            }
        }
    };


    private void showTip(final String str) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (mToast != null) {
                    mToast.cancel();
                }
                mToast = Toast.makeText(context, str, Toast.LENGTH_SHORT);
                mToast.show();
            }
        }).start();
    }

    /**
     * 参数设置
     *
     * @return
     */
    public void setParam() {
        // 设置文本编码格式
        mAsr.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
        // 清空参数
        mAsr.setParameter(SpeechConstant.PARAMS, null);
        // 设置识别引擎
        mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 设置本地识别资源
        mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
        // 设置语法构建路径
        mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
        // 设置返回结果格式
        mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
        // 设置本地识别使用语法id
        mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call");
        // 设置识别的门限值
        mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30");
        // 使用8k音频的时候请解开注释
//			mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");

    }

    //获取识别资源路径
    private String getResourcePath() {
        StringBuffer tempBuffer = new StringBuffer();
        //识别通用资源
        tempBuffer.append(ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "asr/common.jet"));
        return tempBuffer.toString();
    }


    @Override
    public SpeechRecognizer getAsr(Context context) {
        if (null != mAsr) {
            return mAsr;
        }
        myinit(context);
        return mAsr;
    }

    @Override
    public void startListening(RecognizerListener listener) {
        if (null == mAsr) {
            // 创建单例失败，与 21001 错误为同样原因，参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
            this.showTip("创建对象失败，请确认 libmsc.so 放置正确，\n 且有调用 createUtility 进行初始化");
            return;
        }

        if (null == mEngineType) {
            showTip("请先选择识别引擎类型");
            return;
        }

        // 设置音频来源为外部文件
        mAsr.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
        // 也可以像以下这样直接设置音频文件路径识别（要求设置文件在sdcard上的全路径）：
//            mAsr.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
//            mAsr.setParameter(SpeechConstant.ASR_SOURCE_PATH, "sdcard/at/131.pcm");
        ret = mAsr.startListening(listener);
        if (ret != ErrorCode.SUCCESS) {
            showTip("识别失败,错误码：" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
            return;
        }
        try {
            String wavFilePath = Environment.getExternalStorageDirectory().getPath() + File.separator + Environment.DIRECTORY_MUSIC + File.separator + "AsrFile";
            File fileJia = new File(wavFilePath);
            if (!fileJia.exists()) {
                fileJia.mkdirs();
            }
            File wavfile = new File(wavFilePath, curFile);
            if (!wavfile.exists()) {
                showTip("未找到文件：AsrFile 下的" + curFile);
                return;
            }
            InputStream open = new FileInputStream(wavfile);
            //讯飞支持的音频文件格式
            // 只有pcm和wav(这种格式直接忽略，用ffmpeg库转换其他音频格式成wav格式之后，全部都是噪音)，
            // 并且音频文件的参数也有要求：采样率为8khz或16khz，采样精度为16bits，声道为单声道
//                InputStream open = getAssets().open(curFile);
            byte[] buff = new byte[1280];
            while (open.available() > 0) {
                int read = open.read(buff);
                mAsr.writeAudio(buff, 0, read);
            }
            mAsr.stopListening();
        } catch (IOException e) {
            mAsr.cancel();
            showTip("读取音频流失败");
            return;
        }
        showTip("未知错误");
        return;
    }

    @Override
    public void stopListening() {
        mAsr.stopListening();
        mAsr.cancel();
        showTip("取消识别");
    }


}
